#pragma once

#include "Framework2D.h"
Framework2D f2d;

// USE AS GLOBAL FOR MAIN


LPDIRECT3D9 d3d;
/*
Long Pointer to Direct3D

Create a class called iDirect3D9
This pointer is used to access indirectly into the class iDirect3D9
when COM creates it
*/


LPDIRECT3DDEVICE9 d3ddev;
/*
Long Pointerd to Direct3D Device

This interface holds all information to 
	"Graphics Driver, Video Card, and 
	everything else having to do with the hardware side of graphics"
Pointer to the class that holds all these information (The One Who knows it all)
*/

D3DCOLOR screenColor = D3DCOLOR_XRGB(0, 0, 0);			// Black
//D3DCOLOR screenColor = D3DCOLOR_XRGB(255, 255, 255);	// White

/*
FUNCTIONs OF THE MAIN	
*/
void MainInit(HWND& hWnd, HINSTANCE hInst)
{
	d3d = Direct3DCreate9(D3D_SDK_VERSION);
	/*
	Very first Direct3D function that you will run
	Its purpose is to create the Direct3D interface
	Direct3DCreate9 will return an address of the interface created 
		and stored into the Long Pointer to Direct3D

	This parameter will always be the same for every framework that you build or see
		This will tell the user's directX which version you developed your game for


		Durect3D 9 will return the value 32, others will return different values
		NOTE: Do not change this value even if you could, it will cause confusion
	*/

	D3DPRESENT_PARAMETERS d3dpp;

	/*
	There are certain information that veing fed into the graphics device from the start

	d3dpresent_parameters is a member who will contain informaiton about the graphics device
	*/


	ZeroMemory(&d3dpp, sizeof(d3dpp));
	/*
	quickly initialize the entire d3dpp struct to NULL
	*/

	d3dpp.Windowed = TRUE;
	/*
	Enables window mode
	Displaying full screen or window mode is all part of the video card
	*/

	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	/*
	Allows the display driver to select the most efficient presentation technique for the swap chain
	Projecting out is also part of the graphics hardware
	
	*/

	d3dpp.hDeviceWindow = hWnd;
	/*
	Sets the handle to the window Direct3D should use, 
		which is the one we will always be using
	*/

	d3d->CreateDevice(D3DADAPTER_DEFAULT,
					  D3DDEVTYPE_HAL,
					  hWnd,
					  D3DCREATE_SOFTWARE_VERTEXPROCESSING,
					  &d3dpp,
					  &d3ddev);
	/*
	The parameters here will most likely stays the same for every game you write

	This function creates the graphics device interface
	A class will be then created from which will be use to handle all the graphics you need
	Most of the functions you use in direct3D will come from the Long Pointer to Direct3d (d3d)
		to indirectly access iDirect3D9
	*/



	/*FUNCTION's PROTOTYPE*/
	HRESULT CreateDevice(
		UINT Adapter,
		D3DDEVTYPE DeviceType,
		HWND hFocusWindow,
		DWORD BehaviorFlags,
		D3DPRESENT_PARAMETERS *pPresentationParameters,
		IDirect3DDevice9 **ppReturneddeviceInterface);
	/*
	PARAMETERS of the FUNCTION:
		UINT Adapter - unsigned integer that stores a vlue indicating the graphics adapter or video
					   card Direct3D should use. You can be more detailed here and try to find the better graphics card,
					   but Direct3D can take care of that because in most cases there is only one.
					   Set the parameter to D3DADAPTER_DEFAULT to choose the default graphics card

		D3DDEVTYPE DeviceType - There are four possible values for this parameter but we will only use one (D3DDEVTYPE_HAL).
								D3DDEVTYPE_HAL tells Direct3D to use the Hardware Abstraction Layer (H.A.L)
									- indicate that Direct3D should be using be using hardwares to process graphics
									- If it the hardware cannot be used to render something then that something will be render by software
								This will be done automatically but highly possible that it will not be done

		HWND hFocusWindow - hWnd can be set in this as the value is passed in from the winMain()

		DWORD BehaviorFlags - There are plenty of values that be put here but only 3 that will be cover in the tutorial for now
								- D3DCREATE_SOFTWARE_VERTEXPROCESSING
									- All 3D calculations should be done with software
								- D3DCREATE_HARDWARE_VERTEXPROCESSING
									- All 3d calculations should be done with hardware
								- D3DCREATE_MIXED_VERTEXPROCESSING
									- Using a combination of both depending on which Direct3D sees fit
								
							  These three are self explanatory to what they are meant to do, such as processing the vertex with the software.

		D3DPRESENT_PARAMETERS *pPresentationParameters - Pointer to the d3dpp struct. This is filled with the address from &d3dpp

		IDirect3DDevice9 **ppReturnedDeviceInterface - Pointer to a pointer to the graphics device interface
	*/
	f2d.Init(hWnd, hInst);
}


void MainUpdate()
{
	f2d.Update();
}

/*
RENDER FUNCTION (Render a single frame)
*/
void MainRender()
{
	d3ddev->Clear(0, 
				  NULL, 
				  D3DCLEAR_TARGET, 
				  screenColor, 
				  1.0f, 
				  0);

	d3ddev->BeginScene(); // Tells Direct3D that we are ready to render
	/*
	Begin scene locks the video memory that we wanted
	*/
	f2d.Render(d3ddev);
	/*
	Here is where the back buffer begins
	*/
	d3ddev->EndScene(); // Stops the frame from drawing anymore
	/*
	End Scene unlocks and makes it availabe
	*/
	d3ddev->Present(NULL, NULL, NULL, NULL);	// Display the created frame 
}



void MainRelease(void)
{
	d3ddev->Release();	// close the pointer to the graphics
	d3d->Release();		// close the pointer to direct3d9
	f2d.Release();
}




/*
MESSAGE HANDLER
*/
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch(message)
	{
	case WM_DESTROY:
		{
			PostQuitMessage(0);
			return 0;
		}
	case(WM_KEYDOWN): // At any point if a key is pressed
		{
			switch(wParam)
			{
				// Escape Key will close the application
				// Remove/Modify this call when creating a real game with menus, etc.
			case VK_ESCAPE:
				{
					PostQuitMessage(0);
					break;
				}
			}
		}
	}
	return DefWindowProc(hWnd, message, wParam, lParam);
}


/*
SCREEN INFORMATION
*/
struct ScreenInfo {
	LPCSTR Name_Of_Frame;

	int ScreenWidth;
	int ScreenHeight;

	int ScreenStartPosX;
	int ScreenStartPosY;

	ScreenInfo() {
		Name_Of_Frame = "Engine";

		ScreenWidth  = 800;
		ScreenHeight = 600;

		ScreenStartPosX = 0;
		ScreenStartPosY = 0;
	}
	~ScreenInfo() {}
};